import core from '@/core/'
/**
 * 获取所有页面对象。初始化时被赋值
 * key为页面标识
 * value：
 * 	...页面内style的所有信息
 * 	path：以/开头的页面路径
 * 	tabbar：所属的tabbar页面，回到首页就回到tabbar对应的页面表示key
 * 	hideNavBar：是否隐藏了导航栏
 * ……其它可另再自定义，在initial里面获取即可
 * 
 * 要求pages.json文件中pages的写法如下
 * path：固定写法，不可改
 * style：固定写法，里面值可以自定义
 * 	navigationBarTitleText：页面标题同时作为路由标识。要求必须存在且唯一！
 * 	navigationStyle：是否隐藏了导航栏。可选值custom、default。custom表示隐藏了导航栏
 * 	enablePullDownRefresh：是否开启下拉刷新
 * 	...其它固定属性
 * 	以下为自定义属性
 * 	tabbar：所属的tabbar页面，回到首页就回到tabbar对应的页面表示key
 */
const pages = {
	// '官网': {
	// 	tabbar: '',
	// 	hideNavBar: true,
	// 	path: '/pages/index/index',
	// },
}

/**
 * 页面路由初始化
 * 通过读取pages.json获取路由信息：
 * key：路由标识
 * value包含以下内容
 * 	path：页面路径
 * 	tabbar：返回的首页是哪个页面key
 * 	hideNavBar：是否隐藏了导航栏
 * 	leftWindow：是否显示左侧窗口
 *  rightWindow：是否显示右侧窗口
 * 	...其它可自定义
 */
const initial = () => {
	// 获取 pages.json 配置
	var pagesConfig = require('@/pages.json')
	// 访问实际的 pages.json 配置信息
	if (pagesConfig.default) {
		pagesConfig = pagesConfig.default
	}
	// 是否全局隐藏了导航栏
	const hideNavBar = pagesConfig.globalStyle && pagesConfig.globalStyle.navigationStyle === 'custom'
	const handleOnePage = (item, root) => {
		const {path, style = {}} = item
		if (style && style.navigationBarTitleText && !pages[style.navigationBarTitleText]) {
			pages[style.navigationBarTitleText] = {
				...style,
				tabbar: style.tabbar,
				path: '/' + (root ? `${root}/` : '') + path, 
				hideNavBar: hideNavBar || style.navigationStyle === 'custom',
			}
		}
	}
	// 逐页面遍历
	pagesConfig.pages.forEach(obj => handleOnePage(obj))
	// 子包遍历
	pagesConfig.subPackages && pagesConfig.subPackages.forEach((item) => {
		item.pages.forEach(obj => {
			handleOnePage(obj, item.root)
		})
	})
}

// 获取当前页面对象
const getCurrentPageObj = () => {
	var self
	var systempages = getCurrentPages()
	if (systempages.length > 0) {
		var currentPage = systempages[systempages.length - 1]
		if (currentPage.$vm) {
			// 微信小程序的情况
			self = currentPage.$vm
		} else {
			self = currentPage
		}
	}
	return self
}

/**
 * 获取页面标识
 * self：在页面内传的就是this本身，是对象
 * 		 在js如果传值，传的是getCurrentPages()是数组
 * 		 如果没有值，自动获取页面信息的最后一个
 */
const getPageKey = (self) => {
	if (Array.isArray(self)) {
		if (self.length > 0) {
			var currentPage = self[self.length - 1]
			if (currentPage.$vm) {
				self = currentPage.$vm
			} else {
				self = currentPage
			}
		} else {
			self = undefined
		}
	}
	if (!self) {
		self = getCurrentPageObj()
	}
	var fullPath // 该页面的全路径
	if (self) {
		// 获取该页面的页面标识
		const {__page__, route, __route__, $scope} = self
		/**
		 * H5，来自于__page__
		 * 微信小程序，来自于$scope.$page
		 */
		if (__page__) {
			fullPath = __page__.fullPath ? __page__.fullPath.split('?')[0] : __page__.path
		} else if ($scope && $scope.$page && $scope.$page.fullPath) {
			fullPath = $scope.$page.fullPath.split('?')[0]
		} else if (__route__) {
			fullPath = '/' + __route__
		} else if (route) {
			fullPath = '/' + route
		}
	} else {
		const {_route} = getApp() || {}
		if (_route) {
			fullPath = _route.fullPath
		}
	}
	if (fullPath) {
		const arr = Object.keys(pages)
		for (let i = 0; i < arr.length; i++) {
			if (pages[arr[i]].path === fullPath) {
				return arr[i]
			}
		}
	}
	return ''
}

// 获取页面初始化的参数的Key
const keyForStorageRouter = (self) => {
	if (!self) {
		self = getCurrentPageObj()
	}
	var url = ''
	if (self) {
		// 获取该页面的页面标识
		const {__page__, route, __route__, $scope} = self
		/**
		 * H5，来自于__page__
		 * 微信小程序，来自于$scope.$page
		 */
		if (__page__) {
			url = __page__.fullPath || __page__.path
		} else if ($scope && $scope.$page && $scope.$page.fullPath) {
			url = $scope.$page.fullPath
		}
	}
	return `KeyForRoute-${url}`
}

// 存储页面初始化的参数
const writeRouterData = (routerData, self) => {
	core.storage.setData(keyForStorageRouter(self), routerData)
}

// 读取页面初始化的参数
const readRouterData = (self) => {
	const routerData = core.storage.getDataSync(keyForStorageRouter(self)) || undefined
	return routerData
}

// 跳转类型
const typeArr = ['', 'navigateTo', 'redirectTo', 'reLaunch', 'switchTab', 'preloadPage']
/**
 * 页面跳转
 * 
 * url：页面标识，或者路径。路径可以是全路径或者相对于上个页面的相对路径
 * sendData：发送到目标页面的数据
 * type:
 * 	1：uni.navigateTo。保留当前页面，跳转到应用内的某个页面
 * 	2：uni.redirectTo。关闭当前页面，跳转到应用内的某个页面。
 * 	3：uni.reLaunch。关闭所有页面，打开到应用内的某个页面。
 * 	4：uni.switchTab。跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面。
 * 	5：uni.preloadPage。预加载页面，是一种性能优化技术。被预载的页面，在打开时速度更快。https://uniapp.dcloud.net.cn/api/preload-page.html#
 * callback：目标页面反馈到当前的回调
 * data：其它参数。。比如：animationType、animationDuration，以及重写events、success、fail、complete等
 * 
 * 事件使用参考@pages/index.vue
 * 
 * H5，跳转即执行success
 * App，跳转先执行目标页面的生命周期onLoad、onShow、created，然后再执行success
 * 小程序，大概和App相同（created在onLoad之前）
 * 需要一个统一变量core.store.isRefreshed来知晓当前是否是跳转的页面。该变量是使用后恢复true
 */
const to = (url, sendData, type = 1, callback, data) => {
	if (pages[url] && pages[url].path) {
		url = pages[url].path
	}
	if (url) {
		/**
		 * 页面跳转
		 * uni.navigateTo可以通过事件发送参数
		 * 其它不可以通过事件传递参数。尽量不要传，要传则传简单参数，会写入到url中
		 * uni.switchTab则不能带参数
		 */
		if (type === 2 || type === 3) {
			if (sendData) {
				const arr = []
				Object.keys(sendData).forEach(key => {
					arr.push(`${key}=${sendData[key]}`)
				})
				url += `?${arr.join('&')}`
			}
		}
		uni[typeArr[type]]({
			url,
			events: {
				// 为指定事件添加一个监听器，获取被打开页面传送到当前页面的数据
				callbackOfPage: (params) => {
					// 当前的逻辑中，只要打开了目标页面执行了mounted方法就会回调
					console.log('通知页面回调')
					// 页面跳转完成的回调
					callback && callback(params)
				},
			},
			success: (res) => {
				if (res.errMsg.indexOf('ok') > -1) {
					/**
					 * 传递页面参数
					 * 非push方式，则没有该方法，无法传递参数
					 */
					if (res.eventChannel) {
						res.eventChannel.emit('sendDataToOpenedPage', sendData ? core.synctool.copy.all(sendData) : {})
					}
					// 存储页面参数
					if (sendData) {
						writeRouterData(sendData, url)
					}
					console.log('跳转成功：')
					console.log(res)
				} else {
					console.error('跳转出错：')
					console.error(res)
				}
			},
			fail: (err) => {
				console.error('跳转出错：')
				console.error(err)
			},
			...data,
		})
	} else {
		core.showToast('页面标识错误')
	}
}

/**
 * 返回按钮的显示
 * 如果当前页面没有tabbar，则不需显示。默认返回值是0
 * 如果当前页面有tabbar
 * 	当前仅有一个页面，则显示返回当前页面的tabbar。返回值就是tabbar
 * 	当前有超过一个页面，则显示返回上一页。返回值是1
 */
const showBack = () => {
	// 获取当前所有页面
	var systempages = getCurrentPages()
	if (systempages.length > 0) {
		const PageKey = getPageKey(systempages)
		if (PageKey) {
			if (pages[PageKey] && pages[PageKey].tabbar) {
				if (systempages.length === 1) {
					// 返回对应的首页
					return pages[PageKey].tabbar
				}
				// 返回上一页
				return 1
			}
		}
	}
	return 0
}

/**
 * 路由返回 - 关闭当前页面，返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈，决定需要返回几层。
 * 	delta: 返回的页面数，如果 delta 大于现有页面数，则返回到首页。默认值1
 * 	animationType：窗口关闭的动画效果，详见：窗口动画。默认值pop-out App
 * 	animationDuration：窗口关闭动画的持续时间，单位为 ms。默认值300 App
 * 	success
 * 	fail
 */
const back = (data) => {
	// 获取当前所有页面
	var systempages = getCurrentPages()
	// 如果当前仅有一个页面，返回即返回到首页
	if (systempages.length === 1) {
		const PageKey = getPageKey(systempages)
		if (PageKey) {
			if (pages[PageKey] && pages[PageKey].tabbar) {
				// 跳转到首页
				to(pages[PageKey].tabbar, undefined, 3)
			} else {
				console.error('跳转出错：' + PageKey)
			}
		} else {
			console.error('跳转出错：没有PageKey!')
		}
	} else {
		if (!data) {
			data = {
				delta: 1,
				animationType: 'pop-out',
				animationDuration: 300,
				success: (res) => {
					console.log('页面返回完成')
				},
				fail: (err) => {
					console.warn('页面返回失败')
					console.error(err)
				}
			}
		}
		uni.navigateBack(data)
	}
}

export default {
	initial,
	pages,
	getPageKey,
	getCurrentPageObj,
	writeRouterData,
	readRouterData,
	showBack,
	back,
	to
}